package org.example.gui;

import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import org.example.core.DirectoryEntry;
import org.example.core.FileOperations;
import org.example.core.FileSystem;

import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.*;

/**
 * 主图形界面窗口
 */
public class MainWindow extends Application {
    private FileSystem fileSystem;
    private FileOperations fileOps;
    private TableView<DirectoryEntry> fileTable;
    private Label statusLabel;
    private int currentDirectory = 2;// 根目录块号
    private Stack<Integer> directoryHistory = new Stack<>();
    // 完整名称映射，key为"目录块号_截断文件名"，value为完整名称
    private Map<String, String> fullNameMap = new HashMap<>();
    // 映射文件路径
    private static final String MAPPING_FILE = "filename_mappings.properties";


    @Override
    public void start(Stage primaryStage) {
        try {
            // 加载名称映射
            loadNameMappings();

            // 初始化文件系统
            fileSystem = new FileSystem();
            if (!fileSystem.isInitialized()) {
                showAlert("错误", "文件系统初始化失败");
                return;
            }

            // 初始化文件操作
            fileOps = new FileOperations(
                    fileSystem.getDiskEmulator(),
                    fileSystem.getFatManager()
            );

            // 创建主界面
            BorderPane root = new BorderPane();

            // 创建顶部工具栏
            HBox toolbar = createToolbar();
            root.setTop(toolbar);

            // 创建文件表格
            fileTable = createFileTable();
            root.setCenter(fileTable);

            // 创建状态栏
            statusLabel = new Label("就绪");
            root.setBottom(statusLabel);

            // 加载当前目录内容
            refreshFileTable();

            Scene scene = new Scene(root, 800, 600);
            primaryStage.setTitle("磁盘文件系统模拟器 - 根目录");
            primaryStage.setScene(scene);
            primaryStage.show();

        } catch (Exception e) {
            showAlert("启动错误", "无法启动应用程序: " + e.getMessage());
            e.printStackTrace();
        }
    }

    /**
     * 加载名称映射
     */
    private void loadNameMappings() {
        try {
            if (Files.exists(Paths.get(MAPPING_FILE))) {
                Properties props = new Properties();
                try (InputStream input = new FileInputStream(MAPPING_FILE)) {
                    props.load(input);
                    for (String key : props.stringPropertyNames()) {
                        fullNameMap.put(key, props.getProperty(key));
                    }
                }
            }
        } catch (IOException e) {
            System.err.println("加载名称映射失败: " + e.getMessage());
        }
    }

    /**
     * 保存名称映射
     */
    private void saveNameMappings() {
        try {
            Properties props = new Properties();
            for (Map.Entry<String, String> entry : fullNameMap.entrySet()) {
                props.setProperty(entry.getKey(), entry.getValue());
            }
            try (OutputStream output = new FileOutputStream(MAPPING_FILE)) {
                props.store(output, "文件名映射 - 截断名称到完整名称");
            }
        } catch (IOException e) {
            System.err.println("保存名称映射失败: " + e.getMessage());
        }
    }

    /**
     * 获取映射key
     */
    private String getMappingKey(int directoryBlock, String truncatedName) {
        return directoryBlock + "_" + truncatedName;
    }

    /**
     * 创建工具栏
     */
    private HBox createToolbar() {
        HBox toolbar = new HBox(10);
        toolbar.setPadding(new Insets(10));
        toolbar.setStyle("-fx-background-color: #e0e0e0;");

        // 刷新按钮
        Button refreshBtn = new Button("刷新");
        refreshBtn.setOnAction(e -> refreshFileTable());

        // 返回按钮
        Button backBtn = new Button("返回上级目录");
        backBtn.setOnAction(e -> goToParentDirectory());

        // 新建文件按钮
        Button newFileBtn = new Button("新建文件");
        newFileBtn.setOnAction(e -> createNewFile());

        // 新建目录按钮
        Button newDirBtn = new Button("新建目录");
        newDirBtn.setOnAction(e -> createNewDirectory());

        // 删除按钮
        Button deleteBtn = new Button("删除");
        deleteBtn.setOnAction(e -> deleteSelected());

        // 属性按钮
        Button propertiesBtn = new Button("属性");
        propertiesBtn.setOnAction(e -> showProperties());

        // FAT状态按钮
        Button fatStatusBtn = new Button("FAT状态");
        fatStatusBtn.setOnAction(e -> showFATStatus());

        toolbar.getChildren().addAll(
                refreshBtn, backBtn, newFileBtn, newDirBtn,
                deleteBtn, propertiesBtn, fatStatusBtn
        );

        return toolbar;
    }

    /**
     * 创建文件表格
     */
    private TableView<DirectoryEntry> createFileTable() {
        TableView<DirectoryEntry> table = new TableView<>();

        // 名称列
        TableColumn<DirectoryEntry, String> nameCol = new TableColumn<>("名称");
        nameCol.setCellValueFactory(data -> {
            DirectoryEntry entry = data.getValue();
            String displayName = getDisplayName(entry);
            return new SimpleStringProperty(displayName);
        });
        nameCol.setPrefWidth(200);

        // 类型列
        TableColumn<DirectoryEntry, String> typeCol = new TableColumn<>("类型");
        typeCol.setCellValueFactory(data ->
                new SimpleStringProperty(data.getValue().isDirectory() ? "目录" : "文件"));
        typeCol.setPrefWidth(100);

        // 大小列
        TableColumn<DirectoryEntry, String> sizeCol = new TableColumn<>("大小");
        sizeCol.setCellValueFactory(data ->
                new SimpleStringProperty(formatSize(data.getValue().getLength())));
        sizeCol.setPrefWidth(100);

        // 起始块列
        TableColumn<DirectoryEntry, String> blockCol = new TableColumn<>("起始块");
        blockCol.setCellValueFactory(data ->
                new SimpleStringProperty(Integer.toString(data.getValue().getStartBlock() & 0xFF)));
        blockCol.setPrefWidth(80);

        table.getColumns().addAll(nameCol, typeCol, sizeCol, blockCol);

        // 双击打开目录或文件
        table.setRowFactory(tv -> {
            TableRow<DirectoryEntry> row = new TableRow<>();
            row.setOnMouseClicked(event -> {
                if (event.getClickCount() == 2 && !row.isEmpty()) {
                    DirectoryEntry entry = row.getItem();
                    if (entry.isDirectory()) {
                        openDirectory(entry);
                    } else {
                        openFile(entry);
                    }
                }
            });
            return row;
        });

        return table;
    }

    /**
     * 刷新文件表格
     */
    private void refreshFileTable() {
        List<DirectoryEntry> entries = fileOps.listDirectory(currentDirectory);
        ObservableList<DirectoryEntry> observableList = FXCollections.observableArrayList(entries);
        fileTable.setItems(observableList);
        statusLabel.setText("就绪 - 共 " + entries.size() + " 个项目");
    }

    /**
     * 获取显示名称
     */
    private String getDisplayName(DirectoryEntry entry) {
        String truncatedName = entry.getFullName();
        String key = getMappingKey(currentDirectory, truncatedName);
        return fullNameMap.getOrDefault(key, truncatedName);
    }

    /**
     * 截断文件名为3字节
     */
    private String truncateTo3Bytes(String name) {
        if (name == null || name.isEmpty()) {
            return name;
        }

        try {
            byte[] bytes = name.getBytes("UTF-8");
            if (bytes.length <= 3) {
                return name;
            }

            // 截断为3字节，确保不截断多字节字符
            int cutPoint = 3;
            while (cutPoint > 0 && (bytes[cutPoint] & 0x80) != 0 && (bytes[cutPoint] & 0xC0) != 0xC0) {
                cutPoint--;
            }

            if (cutPoint == 0) {
                cutPoint = 3; // 如果无法找到合适的截断点，强制截断
            }

            return new String(bytes, 0, cutPoint, "UTF-8");
        } catch (Exception e) {
            // 如果UTF-8转换失败，简单截断字符串
            return name.length() <= 3 ? name : name.substring(0, 3);
        }
    }

    /**
     * 打开目录
     */
    private void openDirectory(DirectoryEntry directory) {
        // 将当前目录添加到历史
        directoryHistory.push(currentDirectory);

        currentDirectory = directory.getStartBlock() & 0xFF;
        refreshFileTable();
        statusLabel.setText("当前目录: " + getDisplayName(directory));
    }

    /**
     * 打开文件 - 需要实现具体功能
     */
    private void openFile(DirectoryEntry file) {
        // 实现文件打开功能
        showAlert("信息", "打开文件: " + getDisplayName(file) + "\n此功能尚未实现");
    }

    /**
     * 新建文件
     */
    private void createNewFile() {
        TextInputDialog dialog = new TextInputDialog();
        dialog.setTitle("新建文件");
        dialog.setHeaderText("请输入文件名:");
        dialog.setContentText("名称:");

        Optional<String> result = dialog.showAndWait();
        result.ifPresent(fullName -> {
            // 截断文件名为3字节存储
            String truncatedName = truncateTo3Bytes(fullName);

            if (fileOps.createFile(currentDirectory, truncatedName, "txt", DirectoryEntry.NORMAL_FILE)) {
                // 添加到映射，使用复合key
                String key = getMappingKey(currentDirectory, truncatedName);
                fullNameMap.put(key, fullName);
                saveNameMappings(); // 立即保存映射
                refreshFileTable();
                statusLabel.setText("文件创建成功: " + fullName + ".txt");
            } else {
                statusLabel.setText("文件创建失败");
            }
        });
    }

    /**
     * 新建目录
     */
    private void createNewDirectory() {
        TextInputDialog dialog = new TextInputDialog();
        dialog.setTitle("新建目录");
        dialog.setHeaderText("请输入目录名:");
        dialog.setContentText("名称:");

        Optional<String> result = dialog.showAndWait();
        result.ifPresent(fullName -> {
            // 截断目录名为3字节存储
            String truncatedName = truncateTo3Bytes(fullName);

            if (fileOps.createDirectory(currentDirectory, truncatedName)) {
                // 添加到映射，使用复合key
                String key = getMappingKey(currentDirectory, truncatedName);
                fullNameMap.put(key, fullName);
                saveNameMappings(); // 立即保存映射
                refreshFileTable();
                statusLabel.setText("目录创建成功: " + fullName);
            } else {
                statusLabel.setText("目录创建失败");
            }
        });
    }


    /**
     * 删除选中的项目
     */
    private void deleteSelected() {
        DirectoryEntry selected = fileTable.getSelectionModel().getSelectedItem();
        if (selected == null) {
            statusLabel.setText("请先选择一个文件或目录");
            return;
        }
        String displayName = getDisplayName(selected);
        Alert confirm = new Alert(Alert.AlertType.CONFIRMATION);
        confirm.setTitle("确认删除");
        confirm.setHeaderText("确定要删除 '" + selected.getFullName() + "' 吗?");
        confirm.setContentText("此操作无法撤销");

        Optional<ButtonType> result = confirm.showAndWait();
        if (result.isPresent() && result.get() == ButtonType.OK) {
            if (fileOps.deleteEntry(currentDirectory, selected.getName())) {
                // 从映射中删除
                String key = getMappingKey(currentDirectory, selected.getName());
                fullNameMap.remove(key);
                saveNameMappings(); // 立即保存映射
                refreshFileTable();
                statusLabel.setText("删除成功: " + displayName);
            } else {
                statusLabel.setText("删除失败");
            }
        }
    }

    /**
     * 显示属性对话框
     */
    private void showProperties() {
        DirectoryEntry selected = fileTable.getSelectionModel().getSelectedItem();
        if (selected == null) {
            showAlert("提示", "请先选择一个文件或目录");
            return;
        }
        String displayName = getDisplayName(selected);

        Alert dialog = new Alert(Alert.AlertType.INFORMATION);
        dialog.setTitle("属性");
        dialog.setHeaderText(displayName + " 的属性");

        VBox content = new VBox(10);
        content.setPadding(new Insets(10));

        content.getChildren().addAll(
                createPropertyLabel("名称:", displayName),
                createPropertyLabel("类型:", selected.isDirectory() ? "目录" : "文件"),
                createPropertyLabel("起始块:", Integer.toString(selected.getStartBlock() & 0xFF)),
                createPropertyLabel("大小:", formatSize(selected.getLength() & 0xFF)),
                createPropertyLabel("属性:", getAttributesString(selected.getAttributes()))
        );

        dialog.getDialogPane().setContent(content);
        dialog.showAndWait();
    }

    /**
     * 创建属性标签行
     */
    private HBox createPropertyLabel(String label, String value) {
        HBox row = new HBox(5);
        Label nameLabel = new Label(label);
        nameLabel.setStyle("-fx-font-weight: bold;");
        Label valueLabel = new Label(value);
        row.getChildren().addAll(nameLabel, valueLabel);
        return row;
    }

    /**
     * 将属性字节转换为可读字符串
     */
    private String getAttributesString(byte attributes) {
        StringBuilder sb = new StringBuilder();

        if ((attributes & DirectoryEntry.READ_ONLY) != 0) {
            sb.append("只读 ");
        }
        if ((attributes & DirectoryEntry.SYSTEM_FILE) != 0) {
            sb.append("系统 ");
        }
        if ((attributes & DirectoryEntry.NORMAL_FILE) != 0) {
            sb.append("普通文件 ");
        }
        if ((attributes & DirectoryEntry.DIRECTORY) != 0) {
            sb.append("目录 ");
        }

        return sb.toString().trim();
    }

    /**
     * 显示FAT状态
     */
    private void showFATStatus() {
        FATStatusWindow fatWindow = new FATStatusWindow(fileSystem.getFatManager());
        fatWindow.show();
    }

    /**
     * 格式化文件大小
     */
    private String formatSize(int blockCount) {
        int size = blockCount * 64;
        if (size < 1024) {
            return size + " B";
        } else {
            return (size / 1024) + " KB";
        }
    }

    // 返回上级目录方法
    private void goToParentDirectory() {
        if (!directoryHistory.isEmpty()) {
            currentDirectory = directoryHistory.pop();
            refreshFileTable();
            statusLabel.setText("返回上级目录");
        } else {
            showAlert("提示", "已经是根目录，无法返回");
        }
    }

    /**
     * 显示警告对话框
     */
    private void showAlert(String title, String message) {
        Alert alert = new Alert(Alert.AlertType.ERROR);
        alert.setTitle(title);
        alert.setContentText(message);
        alert.showAndWait();
    }

    public static void main(String[] args) {
        launch(args);
    }
}